#include "DocListPlugin.h"

#include <QtCore>
#include <QtCore/QFileInfo>
#include <QtGui/QAction>
#include <QtGui/QContextMenuEvent>
#include <QtGui/QMenu>
#include <QtGui/QLineEdit>
#include <QtGui/QHeaderView>
#include <QtGui/QPushButton>
#include <QtGui/QTreeWidget>
#include <QtGui/QTreeWidgetItem>
#include <QtGui/QVBoxLayout>
#include <QHBoxLayout>

#include "juffed/CommandStorage.h"
#include "juffed/Functions.h"
#include "juffed/TextDocSettings.h"

static const int BtnSize = 24;

class FilterLineEdit : public QWidget {
public:
	FilterLineEdit(QWidget* parent = 0) : QWidget(parent) {
		lineEd_ = new QLineEdit("", this);
		clearBtn_ = new QPushButton(QIcon(":clear"), "", this);
		clearBtn_->setFlat(true);
		clearBtn_->setFocusPolicy(Qt::NoFocus);
		clearBtn_->setCursor(Qt::ArrowCursor);
		clearBtn_->setMaximumWidth(BtnSize);
		
		QHBoxLayout* hBox = new QHBoxLayout(this);
		hBox->setMargin(0);
		hBox->setSpacing(0);
		hBox->addWidget(lineEd_);
#if QT_VERSION >= 0x040500
		lineEd_->setTextMargins(0, 0, BtnSize, 0);
		clearBtn_->setParent(lineEd_);
#else
		hBox->addWidget(clearBtn_);
#endif
	}
	
#if QT_VERSION >= 0x040500
	virtual void resizeEvent(QResizeEvent*) {
		clearBtn_->setGeometry(lineEd_->width() - BtnSize, (lineEd_->height() - BtnSize) / 2, BtnSize, BtnSize);
	}
#endif
	
	QLineEdit* lineEd_;
	QPushButton* clearBtn_;
};

class TreeWidget : public QTreeWidget {
public:
	TreeWidget() : QTreeWidget() {
		contextMenu_ = new QMenu();
		contextMenu_->addAction(Juff::CommandStorage::instance()->action(Juff::ID_FILE_SAVE));
		contextMenu_->addAction(Juff::CommandStorage::instance()->action(Juff::ID_FILE_CLOSE));
	}
	virtual ~TreeWidget() {
		delete contextMenu_;
	}
	
	virtual void contextMenuEvent(QContextMenuEvent * event) {
		contextMenu_->popup(event->globalPos());
	}
	
	QMenu* contextMenu_;
};

class DocListPlugin::Panel : public QWidget {
Q_OBJECT
public:
	Panel() {
		setWindowTitle(tr("Documents"));
		
		tree_ = new TreeWidget();
		filter_ = new FilterLineEdit();
		filter_->setMaximumHeight(24);
		
		QVBoxLayout* vBox = new QVBoxLayout();
		vBox->setMargin(0);
		vBox->setSpacing(2);
		setLayout(vBox);
		
		vBox->addWidget(tree_);
		vBox->addWidget(filter_);
		
		QStringList labels;
		labels << "Name" << "Full name";
		tree_->setHeaderLabels(labels);

		tree_->header()->hide();
		tree_->setColumnHidden(1, true);
		tree_->setRootIsDecorated(false);
		
		connect(filter_->lineEd_, SIGNAL(textChanged(const QString&)), SLOT(filterItems(const QString&)));
		connect(filter_->clearBtn_, SIGNAL(clicked()), SLOT(clear()));
	}
	
	TreeWidget* tree_;
	FilterLineEdit* filter_;
	
public slots:
	void filterItems(const QString& text) {
		int n = tree_->topLevelItemCount();
		for (int i = 0; i < n; ++i) {
			QTreeWidgetItem* item = tree_->topLevelItem(i);
			if ( item->text(0).toLower().contains(text.toLower()) ) {
				item->setHidden(false);
			}
			else {
				item->setHidden(true);
			}
		}
	}
	
	void clear() {
		filter_->lineEd_->setText("");
	}
};

DocListPlugin::DocListPlugin() : QObject(), JuffPlugin() {
	panel_ = new Panel();
	
	connect(panel_->tree_, SIGNAL(itemClicked(QTreeWidgetItem*, int)), SLOT(docClicked(QTreeWidgetItem*, int)));
	connect(panel_->tree_, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(curItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
	
	applySettings();
}

DocListPlugin::~DocListPlugin() { 
}

QString DocListPlugin::name() const {
	return "Documents List";
}

QString DocListPlugin::targetEngine() const {
	return "all";
}

QString DocListPlugin::description() const {
	return "Plugin that allows to view all opened files as a list";
}

QWidgetList DocListPlugin::dockList() const {
	QWidgetList wList;
	wList << panel_;
	return wList;
}

void DocListPlugin::onDocCreated(const QString& fileName) {
	//	if document with this fileName already exists, exit
	if ( !panel_->tree_->findItems(fileName, Qt::MatchFixedString, 1).isEmpty() )
		return;

	QStringList list; 
	if ( Juff::isNoname(fileName) )
		list << tr("Noname") << fileName;
	else
		list << QFileInfo(fileName).fileName() << fileName;
	
	QTreeWidgetItem* item = new QTreeWidgetItem(list);
	item->setIcon(0, QIcon(QString(":doc_icon")));
	item->setToolTip(0, fileName);
	panel_->tree_->addTopLevelItem(item);
	panel_->tree_->setCurrentItem(item);
}

void DocListPlugin::onDocActivated(const QString& fileName)  {
	QList<QTreeWidgetItem*> items = panel_->tree_->findItems(fileName, Qt::MatchFixedString, 1);
	if ( !items.isEmpty() )
		panel_->tree_->setCurrentItem(items[0]);
}

void DocListPlugin::onDocModified(const QString& fileName, bool modified) {
	QList<QTreeWidgetItem*> items = panel_->tree_->findItems(fileName, Qt::MatchFixedString, 1);

	foreach (QTreeWidgetItem* item, items) {
		QString fName = Juff::getDocTitle(fileName);
		if ( modified )
			fName += "*";

		item->setText(0, fName);
	}
}

void DocListPlugin::onDocClosed(const QString& fileName) {
	QList<QTreeWidgetItem*> items = panel_->tree_->findItems(fileName, Qt::MatchFixedString, 1);

	foreach (QTreeWidgetItem* item, items) {
		delete item;
	}
}

void DocListPlugin::onDocRenamed(const QString& oldFileName, const QString& newFileName) {
	QList<QTreeWidgetItem*> items = panel_->tree_->findItems(oldFileName, Qt::MatchFixedString, 1);

	foreach (QTreeWidgetItem* item, items) {
		item->setText(0, Juff::getDocTitle(newFileName));
		item->setText(1, newFileName);
		item->setToolTip(0, newFileName);
	}
}

void DocListPlugin::onTabMoved(int from, int to) {
	QTreeWidgetItem* item = panel_->tree_->takeTopLevelItem(from);
	if ( item ) {
		panel_->tree_->insertTopLevelItem(to, item);
	}
}

void DocListPlugin::curItemChanged(QTreeWidgetItem* it, QTreeWidgetItem*) {
	if ( it )
		manager()->openDoc(it->text(1));
}

void DocListPlugin::applySettings() {
	QPalette plt = panel_->tree_->palette();
	plt.setColor(QPalette::Base, TextDocSettings::defaultBgColor());
	plt.setColor(QPalette::Text, TextDocSettings::defaultFontColor());
	
	QColor selBgColor = TextDocSettings::selectionBgColor();
	plt.setColor(QPalette::Highlight, selBgColor);
	if ( selBgColor.red() + selBgColor.green() + selBgColor.blue() < 3 * 255 / 2)
		plt.setColor(QPalette::HighlightedText, Qt::white);
	else
		plt.setColor(QPalette::HighlightedText, Qt::black);

	panel_->tree_->setPalette(plt);
	panel_->filter_->setPalette(plt);
}

#include "DocListPlugin.moc"

Q_EXPORT_PLUGIN2(doclist, DocListPlugin)
